package models

import (
	"bytes"
	"fmt"
	"gitchina/kly_service/data"
	"gitchina/kly_service/errors"
	"gitchina/kly_service/util"
	"time"
)

// Image ...
type Image struct{}

// UploadImageRQ ...
type UploadImageRQ struct {
	MbrID      ID     `json:"-"`
	Proto      int    `json:"proto"`
	Type       int    `json:"type"`
	Seq        int    `json:"seq"`
	Data       []byte `json:"-"`
	Ext        string `json:"-"`
	CDN        string `json:"-"`
	Location   string `json:"_"`
	BucketName string `json:"_"`
}

var fuzzyMap = map[string]string{
	"0_0": "opdio", //member photo
	"1_1": "aizkl", //member/card_fs
	"1_2": "colwk", //member/card_rs
	"2_1": "erwlk", //carrier_owner/vehicle
	"2_2": "wkmal", //carrier_owner/driving_license
	"2_3": "pkaie", //carrier_owner/vehicle_license_1
	"2_4": "wqkeo", //carrier_owner/vehicle_license_2
	"3_1": "valeq", //cargo_owner/biz_license
	"4_1": "zceqb", //logistics_emp/biz_license
	"4_2": "yqqkd", //logistics_emp/biz_permit
}

// Command ...
type Command interface {
	Exec() (string, error)
}

type uploadAuthImgCmd struct {
	*UploadImageRQ
}

type uploadAdImgCmd struct {
	*UploadImageRQ
}

// Upload ...
func (i Image) Upload(rq *UploadImageRQ) (string, error) {
	return getCmd(rq).Exec()
}

func (u *uploadAuthImgCmd) Exec() (url string, err error) {
	var fn string
	if fn, err = u.save(u.UploadImageRQ); err == nil {
		url, err = u.updateURL(fn, u.UploadImageRQ)
	}
	if err != nil {
		util.GetLogger().Error("[model-uploadimage] - error: %s", err.Error())
		err = errors.New(errors.MSG_Image_Upload_Error)
	}
	return
}

func getCmd(rq *UploadImageRQ) (cmd Command) {
	if rq.Type == 5 {
		return &uploadAdImgCmd{rq}
	}
	return &uploadAuthImgCmd{rq}
}

func (u *uploadAuthImgCmd) save(rq *UploadImageRQ) (fn string, err error) {
	var store Storage
	if fuzzy, ok := getFuzzy(rq); ok {
		if store, err = NewStore(rq.Location); err == nil {
			fn = fmt.Sprintf("auth/%s_%s.%s", rq.MbrID, fuzzy, rq.Ext)
			err = store.Options("fn", fn).
				Options("bucketname", rq.BucketName).
				Save(bytes.NewBuffer(rq.Data))
		}
	}
	return
}

func (u *uploadAuthImgCmd) updateURL(fn string, rq *UploadImageRQ) (url string, err error) {
	var id int64
	var repo data.ImageRepo
	if _, _, _, id, err = rq.MbrID.Decode(); err == nil {
		url = fmt.Sprintf("%s%s?ver=%d", rq.CDN, fn, time.Now().Nanosecond())
		err = repo.AddPhoto(int(id), url, rq.Type, rq.Seq)
	}
	return
}

func getFuzzy(rq *UploadImageRQ) (string, bool) {
	v, ok := fuzzyMap[fmt.Sprintf("%d_%d", rq.Type, rq.Seq)]
	return v, ok
}

func (ad *uploadAdImgCmd) Exec() (url string, err error) {
	var store Storage
	fn := fmt.Sprintf("ad/%d.%s", time.Now().UnixNano(), ad.Ext)
	if store, err = NewStore(ad.Location); err == nil {
		if err = store.Options("fn", fn).
			Options("bucketname", ad.BucketName).
			Save(bytes.NewBuffer(ad.Data)); err == nil {
			url = fmt.Sprintf("%s%s", ad.CDN, fn)
		}
	}
	return
}
